﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum EScrollEnum
{
    None,
    Hover,
    LeftSlide,
    CenterSlide,
    RightSlide,
}
public enum EPanelPointEnum
{
    Left,
    Center,
    Right,
}
public class PanelInfo : MonoBehaviour
{
    public EPanelPointEnum type;
    public Vector3 position;
    public int count;

    protected int _index;
    public int index
    {
        get { return _index; }
    }

    public virtual void UpdatePosition(Vector3 newPosition)
    {
        position = newPosition;
    }

    public virtual void MoveLeft()
    {
        switch (type)
        {
            case EPanelPointEnum.Left:
                type = EPanelPointEnum.Right;
                break;
            case EPanelPointEnum.Center:
                type = EPanelPointEnum.Left;
                break;
            case EPanelPointEnum.Right:
                type = EPanelPointEnum.Center;
                break;
        }
    }

    public virtual void MoveRight()
    {
        switch (type)
        {
            case EPanelPointEnum.Left:
                type = EPanelPointEnum.Center;
                break;
            case EPanelPointEnum.Center:
                type = EPanelPointEnum.Right;
                break;
            case EPanelPointEnum.Right:
                type = EPanelPointEnum.Left;
                break;
        }
    }

    public void OnDestroy()
    {
        Dispose();
    }

    public virtual void OnUpdate() { }

    public virtual void Dispose() { }

}
public class ScrollRect3DComponent
{

    private readonly float slideSpeed = 5;
    private readonly float slideBackSpeed = 0.5f;

    public int CenterIndex
    {
        get
        {
            foreach (PanelInfo info in panelArray)
            {
                if (info.type == EPanelPointEnum.Center)
                    return info.index;
            }
            return 0;
        }
    }

    public PanelInfo[] panelArray;

    private EScrollEnum m_currentType;

    private Vector3 m_downPoint;
    private Vector3 m_previousPoint;

    private Vector3 m_leftPoint;
    private Vector3 m_centerPoint;
    private Vector3 m_rightPoint;

    private bool bPlaying;
    private bool bHover = false;
    private bool bLoop;

    private int m_count;

    private float m_rate;
    private float m_hoverRate;

    private System.Action<int> m_changeCallback;

    /// <summary>
    /// 
    /// </summary>
    /// <param name="leftInfo"></param>
    /// <param name="centerInfo"></param>
    /// <param name="rightInfo"></param>
    /// <param name="centerPoint"></param>
    /// <param name="rightPoint"></param>
    /// <param name="count"></param>
    /// <param name="loop"></param>
    /// <param name="changeCallback">页数回调 从 0 开始</param>
    public void Initialize(PanelInfo leftInfo, PanelInfo centerInfo, PanelInfo rightInfo, Vector3 centerPoint, Vector3 rightPoint, int count, bool loop, System.Action<int> changeCallback = null)
    {
        panelArray = new PanelInfo[] { leftInfo, centerInfo, rightInfo };

        m_leftPoint = centerPoint + centerPoint - rightPoint;
        m_centerPoint = centerPoint;
        m_rightPoint = rightPoint;
        
        m_count = count;
        bLoop = loop;
        m_changeCallback = changeCallback;

        leftInfo.type = EPanelPointEnum.Left;
        leftInfo.position = centerPoint + centerPoint - rightPoint;
        leftInfo.count = count;

        centerInfo.type = EPanelPointEnum.Center;
        centerInfo.position = centerPoint;
        centerInfo.count = count;

        rightInfo.type = EPanelPointEnum.Right;
        rightInfo.position = centerPoint + rightPoint - centerPoint;
        rightInfo.count = count;

        bHover = false;
        bPlaying = true;
        m_currentType = EScrollEnum.None;
    }

    public void OnUpdate(float deltaTime)
    {
        if (!bPlaying)
            return;

        if (bHover)
        {
            Vector3 direction = Input.mousePosition - m_previousPoint;
            m_hoverRate = direction.x / Screen.width;
            m_previousPoint = Input.mousePosition;
        }

        UpdateInfo();
        //Debug.Log(m_rate);
    }

    private void UpdateInfo()
    {
        switch (m_currentType)
        {
            case EScrollEnum.Hover:
                m_rate += m_hoverRate;
                break;
            case EScrollEnum.LeftSlide:
                m_rate -= Time.deltaTime * slideSpeed;
                break;
            case EScrollEnum.RightSlide:
                m_rate += Time.deltaTime * slideSpeed;
                break;
            case EScrollEnum.CenterSlide:
                if (m_rate > 0)
                    m_rate -= Time.deltaTime * slideBackSpeed;
                else if(m_rate < 0)
                    m_rate += Time.deltaTime * slideBackSpeed;
                break;
        }

        if (CenterIndex == 0 && !bLoop && m_rate > 0)
        {
            m_rate = 0;
            m_currentType = EScrollEnum.None;
        }
        if (CenterIndex == m_count - 1 && !bLoop && m_rate < 0)
        {
            m_rate = 0;
            m_currentType = EScrollEnum.None;
        }

        switch (m_currentType)
        {
            case EScrollEnum.Hover:
            case EScrollEnum.LeftSlide:
            case EScrollEnum.RightSlide:

                if (m_rate < -1)
                {
                    m_rate = -1;
                    m_currentType = EScrollEnum.None;
                }
                else if (m_rate > 1)
                {
                    m_rate = 1;
                    m_currentType = EScrollEnum.None;
                }
                MoveInfo();
                break;
            case EScrollEnum.CenterSlide:
                if (m_rate < 0.01f && m_rate > -0.01f)
                {
                    m_rate = 0;
                    m_currentType = EScrollEnum.None;
                }

                MoveInfo();
                break;
        }
    }

    private void MoveInfo()
    {
        bool bRight = m_rate >= 1;
        bool bLeft = m_rate <= -1;
        if (bRight)
        {
            m_rate -= 1;
        }
        if (bLeft)
        {
            m_rate += 1;
        }

        Vector3 direction = m_rightPoint - m_centerPoint;
        Vector3 moveDir = m_rate * direction;
        foreach (PanelInfo info in panelArray)
        {
            if (bRight)  // to right
            {
                info.MoveRight();
            }
            else if (bLeft)   // to left
            {
                info.MoveLeft();
            }
            switch (info.type)
            {
                case EPanelPointEnum.Left:
                    info.UpdatePosition(m_leftPoint + moveDir);
                    break;
                case EPanelPointEnum.Center:
                    info.UpdatePosition(m_centerPoint + moveDir);
                    break;
                case EPanelPointEnum.Right:
                    info.UpdatePosition(m_rightPoint + moveDir);
                    break;
            }
        }

        if (bRight || bLeft)
        {
            if (m_changeCallback != null)
                m_changeCallback(CenterIndex);
        }
    }

    public void OnDown()
    {
        if (m_currentType != EScrollEnum.None)
            return;

        m_currentType = EScrollEnum.Hover;
        m_downPoint = m_previousPoint = Input.mousePosition;
        bHover = true;
    }

    public float OnUp()
    {
        if (!bHover)
            return 0;

        bHover = false;

        Vector3 direction = Input.mousePosition - m_downPoint;
        float dragRate = direction.x / Screen.width;
        float minRate = 0.1f;
        if (dragRate > minRate)
        {
            MovePanel(EScrollEnum.RightSlide);
        }
        else if (dragRate < -minRate)
        {
            MovePanel(EScrollEnum.LeftSlide);
        }
        else
        {
            MovePanel(EScrollEnum.CenterSlide);
        }
        return dragRate;
    }

    public void MovePanel(EScrollEnum type)
    {
        if (CenterIndex == 0 && !bLoop && type == EScrollEnum.RightSlide)
        {
            return;
        }
        if (CenterIndex == m_count - 1 && !bLoop && type == EScrollEnum.LeftSlide)
        {
            return;
        }
        m_currentType = type;
    }

    public void Reset()
    {
        m_currentType = EScrollEnum.None;
        m_rate = m_hoverRate = 0;
        foreach (PanelInfo info in panelArray)
        {
            switch (info.type)
            {
                case EPanelPointEnum.Left:
                    info.UpdatePosition(m_leftPoint);
                    break;
                case EPanelPointEnum.Center:
                    info.UpdatePosition(m_centerPoint);
                    break;
                case EPanelPointEnum.Right:
                    info.UpdatePosition(m_rightPoint);
                    break;
            }
        }
    }

    public void Dispose()
    {
        bPlaying = false;
    }

    

    	
}
